home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
util
/
gnu
/
oleo_src.lha
/
src
/
io_term.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-18
|
80KB
|
3,817 lines
/* Copyright (C) 1990 Free Software Foundation, Inc.
This file is part of Oleo, the GNU Spreadsheet.
Oleo is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
Oleo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Oleo; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>
#ifdef I_IOCTL
#include <sys/ioctl.h>
#endif
#include "funcdef.h"
#define obstack_chunk_alloc ck_malloc
#define obstack_chunk_free free
#include "obstack.h"
#ifdef __TURBOC__
#define RCFILE "oleo.rc"
#else
#define RCFILE ".oleorc"
#endif
#include "sysdef.h"
#include "global.h"
#include "cell.h"
#include "kbd.h"
#define CTRL(X) ((X)&037)
#define LINE_MIN 28
#ifdef __TURBOC__
#define TIMER_MULT 10000
#else
#if defined(NO_UALARM) && !defined(SETITIMER)
#define TIMER_MULT 1/10
#else
#define TIMER_MULT 100000
#endif
#endif
/* Structures for this file */
/* for func_flags */
#define NONTOP 0x1
#define TOPLN 0x2
#define ALL 0x3
#define WTH_CHR 0x4
#define BRK 0x8
#define NC 0x10
struct line {
int alloc;
char *buf;
};
struct macro {
struct macro *mac_prev;
unsigned char *mac_exe;
int mac_flags;
CELLREF mac_row, mac_col;
struct rng mac_rng;
};
/* External spreadsheet functions */
/* utils.c */
extern char *char_to_string EXT1(char);
extern int string_to_char EXT1(char **);
extern FILE *xopen_with_backup EXT2(const char *,const char *);
extern int xclose EXT1(FILE *);
extern char *err_msg EXT0();
extern char *mk_sprintf EXT1N(char *);
extern void init_mem EXT0();
extern void init_eval EXT0();
extern void init_refs EXT0();
extern void init_cells EXT0();
extern void panic_read_file EXT2(FILE *,int);
extern void panic_write_file EXT2(FILE *,struct rng *);
extern int panic_set_options EXT2(int, char *);
extern void panic_show_options EXT0();
#ifdef USE_DLD
/* If we're using dynamic linking, we get the names of the
functions to call by prepending the basename of save_name onto
_read_file
_write_file
_set_options
_show_options
so, if the file is sylk.o , the functions are named
sylk_read_file
sylk_write_file
sylk_set_options
sylk_show_options
*/
char *io_name;
#else
extern void sylk_read_file EXT2(FILE *,int);
extern void sylk_write_file EXT2(FILE *,struct rng *);
extern int sylk_set_options EXT2(int, char *);
extern void sylk_show_options EXT0();
extern void sc_read_file EXT2(FILE *,int);
extern void sc_write_file EXT2(FILE *,struct rng *);
extern int sc_set_options EXT2(int, char *);
extern void sc_show_options EXT0();
extern void list_read_file EXT2(FILE *,int);
extern void list_write_file EXT2(FILE *,struct rng *);
extern int list_set_options EXT2(int, char *);
extern void list_show_options EXT0();
/* extern char sl_sep; */
#endif
/* regions.c */
extern void set_rng EXT5(struct rng *, CELLREF, CELLREF, CELLREF, CELLREF);
extern void lock_region EXT2(struct rng *, int);
extern void format_region EXT3(struct rng *, int, int);
extern unsigned short print_width;
/* ref.c */
extern int eval_next_cell EXT0();
extern struct var *find_var EXT2(char *, int);
extern timer_active;
/* io_utils.c */
extern void get_usr_stats EXT2(int, char **);
extern void set_usr_stats EXT2(int, char **);
/* io_disp.c */
extern void redisp EXT0();
extern void open_display EXT1(int);
extern void clear_top_before EXT0();
extern void clear_top_after EXT0();
extern void close_display();
extern void disp_scrn EXT0();
extern int get_chr_prompt EXT1(char *);
extern void recenter_cur_win EXT0();
extern void recenter_all_win EXT0();
extern void cur_status EXT0();
extern int move_cell_cursor EXT2(CELLREF, CELLREF);
extern int get_inp_line EXT2(char *, struct line *);
/* utils.c */
extern char *myname;
extern int __make_backups;
extern int __backup_by_copying;
/* Routines for manipulating 'struct line's */
void set_line EXT2(struct line *, char *);
/* Terminal I/O functions */
int get_chr EXT0();
static unsigned char real_get_chr EXT0();
/* Routines for manipulating key bindings */
static void do_bind_key EXT4(struct keymap *, int, unsigned char, unsigned char);
static void desc_map EXT1(struct keymap *);
/* File I/O functions */
static FILE *open_file EXT3(char *, struct line *, char *);
static void close_file EXT2(struct line *, FILE *);
/* Routines for putting info into 'struct rng's */
static int get_two_ranges EXT4(char *, struct rng *, struct rng *, struct line *);
static FILE * get_range_and_file EXT3(char *, struct rng *, struct line *);
static int get_a_range EXT3(char *,struct rng *,struct line *);
static int get_abs_rng EXT2(char **, struct rng *);
static void sprint_line EXT2N(struct line *, char *);
/* Routines for converting text<-->cell_format */
static int str_to_fmt EXT1(char *);
/* Routines for converting text<-->cell_jst */
static int chr_to_jst EXT1(int);
/* Routines for implementing user commands */
int global_cmd EXT1(int);
void set_options EXT1(char *);
/* Backends for other functions */
static int do_set_option EXT1(char *);
/* Spreadsheet (global) functions declared in this file */
int main EXT2(int, char **);
void map_chr EXT1(int);
extern void clear_spreadsheet EXT0();
void pr_cell EXT3(CELLREF, CELLREF, CELL *);
char *cell_name EXT2(CELLREF, CELLREF);
char *range_name EXT1(struct rng *);
char *fmt_to_str EXT1(int);
char *jst_to_str EXT1(int);
#ifdef A0_REFS
char *col_to_str EXT1(CELLREF);
#endif
const int colmagic[] = {
0, 0, 1,-1, 1,-1, 1,-1, 0};
const int rowmagic[] = {
-1, 1, 0, 0,-1,-1, 1, 1, 0};
char * ename[] = {
"#WHAT?",
"#ERROR", "#BAD_INPUT", "#NON_NUMBER", "#NON_STRING",
"#NON_BOOL", "#NON_RANGE", "#OUT_OF_RANGE","#NO_VALUES",
"#DIV_BY_ZERO", "#BAD_NAME", "#NOT_AVAIL", "#PARSE_ERROR",
"#NEED_OPEN", "#NEED_CLOSE", "#NEED_QUOTE", "#UNK_CHAR",
"#UNK_FUNC",
0
};
const char tname[] = "#TRUE";
const char fname[] = "#FALSE";
int cur_chr;
struct cmd_func *cur_cmd;
unsigned char cur_vector;
/* User settable options */
int bkgrnd_recalc = 1;
int auto_recalc = 1;
/* Original value is 10 seconds/tick */
unsigned signal_ticks = 10 * TIMER_MULT;
void (*read_file) EXT2(FILE *,int) = panic_read_file;
void (*write_file) EXT2(FILE *,struct rng *) = panic_write_file;
int (*set_file_opts) EXT2(int, char *) = panic_set_options;
void (*show_file_opts) EXT0() = panic_show_options;
int n_bound_macros;
struct rng *bound_macros;
int bound_macro_vec;
char *macro_func_arg = 0;
/* This variable is non-zero if the spreadsheet has been changed in any way */
int modified = 0;
CELLREF setrow,
setcol;
CELLREF curow = MIN_ROW,
cucol = MIN_COL;
CELLREF mkrow = NON_ROW,
mkcol = NON_COL;
struct rng mkrng;
/* CELLREF srl,srh,scl,sch; */
unsigned int how_many = 1;
static struct macro *rmac = 0;
static struct obstack macro_stack;
static unsigned char *making_macro;
static unsigned char *making_macro_start;
static unsigned int making_macro_size;
/* If 2, clear the top line before reading a character */
/* if 1, clear it after reading a char */
int topclear = 0;
struct line val_line;
struct line fmt_line;
struct line wid_line;
/* Lines 'a' through 'z' */
struct line in_line[26];
unsigned short default_width=8;
int default_jst = JST_LFT;
int default_fmt = FMT_GEN;
int default_lock = LCK_UNL;
#ifndef __TURBOC__
char buf[BUFSIZ];
int term_flag;
void got_sigio EXT1(int);
#endif
static void got_sigint EXT1(int);
extern char print_buf[];
struct keymap **the_maps;
char **map_names;
int num_maps;
struct cmd_func **the_funcs;
int num_funcs;
/* Keymap stuff: This is the 'main' keymap */
#define GO_UP_CMD 1 /* We want these-all to be low */
#define GO_DN_CMD 2 /* numbers so that rowmagic and */
#define GO_RT_CMD 3 /* colmagic can be small arrays */
#define GO_LF_CMD 4 /* Also note that GO, SCR, and */
#define GO_UPRT_CMD 5 /* MAGIC mumble must all be in */
#define GO_UPLF_CMD 6 /* the same order, and they */
#define GO_DNRT_CMD 7 /* must all agree with rowmagic */
#define GO_DNLF_CMD 8 /* and colmagic */
#define SCR_UP_CMD 9
#define SCR_DN_CMD 10
#define SCR_RT_CMD 11
#define SCR_LF_CMD 12
#define SCR_UPRT_CMD 13
#define SCR_UPLF_CMD 14
#define SCR_DNRT_CMD 15
#define SCR_DNLF_CMD 16
#define SCAN_UP_CMD 17
#define SCAN_DN_CMD 18
#define SCAN_RT_CMD 19
#define SCAN_LF_CMD 20
#define BREAK_CMD 21
#define RECENTER_CMD 22
#define SET_OPT_CMD 23
#define SET_DEF_CMD 24
#define QUIT_CMD 25
#define REDRAW_CMD 26
#define USR_FMT_CMD 27
#define SET_VAR_CMD 28
#define SHO_VAR_CMD 29
#define SHO_ALL_VAR_CMD 30
#define RECALC_CMD 31
#define BIND_KEY_CMD 32
#define DESC_KEY_CMD 33
#define READ_KEY_CMD 34
#define SAVE_KEY_CMD 35
#define WRITE_ALL_CMD 36
#define READ_ALL_CMD 37
#define READ_MERGE_CMD 38
#define KILL_ALL_CMD 39
#define COPY_REG 40
#define COPY_VAL_REG 41
#define FORMAT_REG 42
#define MOVE_REG 43
#define PRINT_REG 44
#define SORT_REG 45
#define WRITE_REG 46
#define KILL_REG 47
#define START_MACRO 48
#define EXECUTE_MACRO 49
#define INTERACT_MACRO 50
#define GOTO_CMD 51
#define SET_MARK_CMD 52
#define EDIT_CELL 53
#define EDIT_VAL_CELL 54
#define FORMAT_CELL 55
#define KILL_CELL 56
#define NEW_DEF_CELL 57
#define DIGIT_0 58
#define DIGIT_1 59
#define DIGIT_2 60
#define DIGIT_3 61
#define DIGIT_4 62
#define DIGIT_5 63
#define DIGIT_6 64
#define DIGIT_7 65
#define DIGIT_8 66
#define DIGIT_9 67
#define NEW_CELL 68
#define SHOW_OPT_CMD 69
#define OPEN_WIN_CMD 70
#define CLOSE_WIN_CMD 71
#define GOTO_WIN_CMD 72
#define END_MACRO 73
#define MK_KEYMAP 74
#ifdef TEST
#define DEBUG_CMD 75
#endif
static struct key main_keys_1[] = {
{ 0, SET_MARK_CMD }, /* ^@ */
{ 0, UNBOUND },
{ 0, GO_LF_CMD },
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 0, UNBOUND }, /* ^E */
{ 0, GO_RT_CMD },
{ 0, BREAK_CMD },
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 0, UNBOUND }, /* ^J */
{ 0, UNBOUND },
{ 0, RECENTER_CMD },
{ 0, UNBOUND },
{ 0, GO_DN_CMD },
{ 0, UNBOUND }, /* ^O */
{ 0, GO_UP_CMD },
{ 0, UNBOUND },
{ 0, REDRAW_CMD },
{ 0, UNBOUND },
{ 0, UNBOUND }, /* ^T */
{ 0, UNBOUND },
{ 0, SHO_ALL_VAR_CMD },
{ 0, UNBOUND },
{ 0, KILL_ALL_CMD },
{ 0, UNBOUND }, /* ^Y */
{ 0, UNBOUND },
{ 255, META_MAP }, /* ^[ */
{ 0, UNBOUND }, /* ^\ */
{ 0, UNBOUND }, /* ^] */
{ 0, UNBOUND }, /* ^^ */
{ 0, UNBOUND }, /* ^_ */
{ 0, NEW_CELL }, /* space */
{ 0, RECALC_CMD }, /* ! */
{ 0, NEW_CELL }, /* " */
{ 0, NEW_CELL }, /* # */
{ 0, NEW_CELL }, /* $ */
{ 0, UNBOUND }, /* % */
{ 0, UNBOUND }, /* & */
{ 0, UNBOUND }, /* ' */
{ 0, NEW_CELL }, /* ( */
{ 0, UNBOUND }, /* ) */
{ 0, UNBOUND }, /* * */
{ 0, NEW_CELL }, /* + */
{ 0, UNBOUND }, /* , */
{ 0, NEW_CELL }, /* - */
{ 0, NEW_CELL }, /* . */
{ 0, UNBOUND }, /* / */
{ 0, NEW_CELL }, /* 0 */
{ 0, NEW_CELL }, /* 1 */
{ 0, NEW_CELL }, /* 2 */
{ 0, NEW_CELL }, /* 3 */
{ 0, NEW_CELL }, /* 4 */
{ 0, NEW_CELL }, /* 5 */
{ 0, NEW_CELL }, /* 6 */
{ 0, NEW_CELL }, /* 7 */
{ 0, NEW_CELL }, /* 8 */
{ 0, NEW_CELL }, /* 9 */
{ 0, BIND_KEY_CMD }, /* : */
{ 0, DESC_KEY_CMD }, /* ; */
{ 0, UNBOUND }, /* < */
{ 0, NEW_DEF_CELL }, /* = */
{ 0, UNBOUND }, /* > */
{ 0, UNBOUND }, /* ? */
{ 0, NEW_CELL }, /* @ */
{ 0, UNBOUND }, /* A */
{ 0, SCR_DNLF_CMD },
{ 0, COPY_VAL_REG },
{ 0, UNBOUND },
{ 0, EDIT_VAL_CELL },
{ 0, FORMAT_REG }, /* F */
{ 0, UNBOUND },
{ 0, SCR_LF_CMD },
{ 0, UNBOUND },
{ 0, SCR_DN_CMD },
{ 0, SCR_UP_CMD }, /* K */
{ 0, SCR_RT_CMD },
{ 0, UNBOUND },
{ 0, SCR_DNRT_CMD },
{ 0, SHOW_OPT_CMD },
{ 0, UNBOUND }, /* P */
{ 0, QUIT_CMD },
{ 0, READ_MERGE_CMD },
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 0, SCR_UPRT_CMD }, /* U */
{ 0, SHO_VAR_CMD },
{ 0, WRITE_REG },
{ 0, KILL_REG },
{ 0, SCR_UPLF_CMD },
{ 0, UNBOUND }, /* Z */
{ 0, UNBOUND }, /* [ */
{ 0, UNBOUND }, /* \ */
{ 0, UNBOUND }, /* ] */
{ 0, UNBOUND }, /* ^ */
{ 0, UNBOUND }, /* _ */
{ 0, UNBOUND }, /* ` */
{ 0, UNBOUND }, /* a */
{ 0, GO_DNLF_CMD },
{ 0, COPY_REG },
{ 0, SET_DEF_CMD },
{ 0, EDIT_CELL },
{ 0, FORMAT_CELL }, /* f */
{ 0, GOTO_CMD },
{ 0, GO_LF_CMD },
{ 0, UNBOUND },
{ 0, GO_DN_CMD },
{ 0, GO_UP_CMD }, /* k */
{ 0, GO_RT_CMD },
{ 0, MOVE_REG },
{ 0, GO_DNRT_CMD },
{ 0, SET_OPT_CMD },
{ 0, PRINT_REG }, /* p */
{ 0, UNBOUND },
{ 0, READ_ALL_CMD },
{ 0, SORT_REG },
{ 0, UNBOUND },
{ 0, GO_UPRT_CMD }, /* u */
{ 0, SET_VAR_CMD },
{ 0, WRITE_ALL_CMD },
{ 0, KILL_CELL },
{ 0, GO_UPLF_CMD } /* y */
};
static struct key main_keys_2[] = {
{ 255, ANSI_MAP } /* CSI , 0x9b hopefully */
};
struct keymap main_map[] = {
{&main_map[1], 0, 0, 1,
'\0','y',
&main_keys_1[0]},
{0, 1, 0, 1,
'\233','\233',
&main_keys_2[0]}
};
/* The meta-map, for key sequences that start with escape */
/* We declare these in reverse order so we won't have to forward-reference
all the pointers. . . */
static struct key meta_key_4[] = {
{ 0, USR_FMT_CMD },
{ 0, UNBOUND },
{ 0, OPEN_WIN_CMD },
{ 0, EXECUTE_MACRO },
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 255, ANSI_MAP }
};
static struct key meta_key_3[] = {
{ 0, CLOSE_WIN_CMD },
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 0, GOTO_WIN_CMD },
{ 0, SCAN_LF_CMD },
{ 0, UNBOUND },
{ 0, SCAN_DN_CMD },
{ 0, SCAN_UP_CMD },
{ 0, SCAN_RT_CMD },
};
static struct key meta_key_2[] = {
{ 0, DIGIT_0 },
{ 0, DIGIT_1 },
{ 0, DIGIT_2 },
{ 0, DIGIT_3 },
{ 0, DIGIT_4 },
{ 0, DIGIT_5 },
{ 0, DIGIT_6 },
{ 0, DIGIT_7 },
{ 0, DIGIT_8 },
{ 0, DIGIT_9 },
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 0, READ_KEY_CMD },
{ 0, UNBOUND },
{ 0, SAVE_KEY_CMD }
};
static struct key meta_key_1[] = {
{ 0, START_MACRO },
{ 0, END_MACRO }
};
#ifdef TEST
#define DBG_ADD 1
static struct key meta_key_0 = { 0, DEBUG_CMD };
#else
#define DBG_ADD 0
#endif
struct keymap meta_map[] = {
#ifdef TEST
{
&meta_map[DBG_ADD], 0, 0, 1,
CTRL('d'),CTRL('d'),
&meta_key_0
},
#endif
{
&meta_map[1+DBG_ADD], 0, 0, 1,
'(',')',
&meta_key_1[0]
},{
&meta_map[2+DBG_ADD], 0, 0, 0,
'0','>',
&meta_key_2[0]
},{
&meta_map[3+DBG_ADD], 0, 0, 0,
'C', 'L',
&meta_key_3[0]
},{
&meta_map[4+DBG_ADD], 0, 0, 0,
'U','[',
&meta_key_4[0]
},{
&meta_map[5+DBG_ADD], 0, 0, 0,
'c', 'l',
&meta_key_3[0],
},{
0, 1, 0, 0,
'u', 'x',
&meta_key_4[0]
}
};
/* For keyboards that return ^[ [ {A B C D} for the arrow keys */
static struct key ansi_key[] = {
{ 0, GO_UP_CMD },
{ 0, GO_DN_CMD },
{ 0, GO_RT_CMD },
{ 0, GO_LF_CMD }
};
struct keymap ansi_map = {
0, 1, 0, 1,
'A', 'D',
&ansi_key[0]
};
/* FOr dealing with meta-digit commands */
static struct keymap digit_map = {
&main_map[0], 1, 0, 0,
'0','9',
&meta_key_2[0]
};
/* The user commands that are defined in this file. . . */
extern void scroll_cell_cursor EXT1(int);
extern void copy_region();
extern void copy_values_region();
extern void set_format();
extern void move_region();
extern void delete_region();
extern void format_area();
extern void open_window();
extern void close_window();
extern void goto_window();
extern void print_region EXT2(struct rng *, char *);
static void do_debug EXT1(char *);
static void end_macro EXT0();
/* static void do_ansi_cmd EXT0(); */
static void do_break_cmd EXT0();
static void set_default EXT0();
static void quit_cmd EXT0();
static void set_usr_fmt EXT1(char *);
static void set_var EXT1(char *);
static void show_var EXT1(char *);
static void show_all_var EXT0();
static void recalc_cmd EXT0();
static void bind_key_cmd EXT1(char *);
static void desc_key_cmd EXT0();
static void read_cmds_cmd EXT1(FILE *);
static void write_keys_cmd EXT1(FILE *);
static void write_cmd EXT1(FILE *);
static void read_cmd EXT1(FILE *);
static void read_merge_cmd EXT1(FILE *);
static void kill_all_cmd EXT0();
static void sort_region_cmd EXT1(char *);
static void write_reg_cmd EXT2(FILE *, struct rng *);
static void start_macro EXT0();
static void execute_cmd EXT1(char *);
static void interact_macro_cmd EXT0();
static void goto_region EXT1(struct rng *);
static void mark_cell_cmd EXT0();
static void do_input_cmd EXT2(int, int);
static void format_cell_cmd EXT0();
static void kill_cell_cmd EXT0();
static void digit_cmd EXT1(int);
static void show_options EXT0();
static void bound_macro EXT1(int);
static void make_keymap EXT1(char *);
static void scan_cell_cursor EXT1(int);
static void shift_cell_cursor EXT1(int);
/* For lines that take text input, the second letter (eg 'ta' or 'fdr')
specifies which struct line to use to contain the text generated for that
command. That way, the command will have the appropriate defaults, etc.
Currently 'a' through 'n' are used (?).
a set options
b set/show variables
c read/write keymap
d read/write file
e read-merge write-region
f copy region/copy values region
g format-region
h move-region
i print-region
j sort-region
k delete-region
l execute-command
m goto-cell
n open-window
o close-window
p debug
q bind-key
r set-user-format
s create-keymap
*/
static struct cmd_func cmd_funcs[] = {
{ "unbound", 0, ALL, 0 },
{ "go-up", "n0", ALL, shift_cell_cursor },
{ "go-down", "n1", ALL, shift_cell_cursor },
{ "go-right", "n2", ALL, shift_cell_cursor },
{ "go-left", "n3", ALL, shift_cell_cursor },
{ "go-upright", "n4", ALL, shift_cell_cursor },
{ "go-upleft", "n5", ALL, shift_cell_cursor },
{ "go-downright", "n6", ALL, shift_cell_cursor },
{ "go-downleft", "n7", ALL, shift_cell_cursor },
{ "scroll-up", "n0", ALL, scroll_cell_cursor },
{ "scroll-down", "n1", ALL, scroll_cell_cursor },
{ "scroll-right", "n2", ALL, scroll_cell_cursor },
{ "scroll-left", "n3", ALL, scroll_cell_cursor },
{ "scroll-upright", "n4", ALL, scroll_cell_cursor },
{ "scroll-upleft", "n5", ALL, scroll_cell_cursor },
{ "scroll-downright", "n6", ALL, scroll_cell_cursor },
{ "scroll-downleft", "n7", ALL, scroll_cell_cursor },
{ "scan-up", "n0", ALL, scan_cell_cursor },
{ "scan-down", "n1", ALL, scan_cell_cursor },
{ "scan-right", "n2", ALL, scan_cell_cursor },
{ "scan-left", "n3", ALL, scan_cell_cursor },
{ "break", 0, ALL|BRK,do_break_cmd },
{ "recenter-window", 0, ALL, recenter_cur_win },
{ "set-option", "ta", ALL, set_options },
{ "set-defaults", "T", ALL, set_default },
{ "quit", "C", ALL, quit_cmd },
{ "redraw-screen", 0, ALL, disp_scrn },
{ "set-user-format", "trT", ALL, set_usr_fmt },
/* If you change the line used by {set,show}-variable, you must change
{set,show}_var to use the correct line, else bad things will happen */
{ "set-variable", "tb", ALL, set_var },
{ "show-variable", "tb", ALL, show_var },
{ "show-all-variables", 0, ALL, show_all_var },
{ "recalculate", 0, ALL, recalc_cmd },
{ "bind-key", "tqT", ALL, bind_key_cmd },
{ "describe-key", "T", ALL, desc_key_cmd },
{ "read-commands", "fcr", ALL, read_cmds_cmd },
{ "write-keys", "fcw", ALL, write_keys_cmd },
/* If you change the line used by {read,write}-file, you must change
main() to use the correct line, else chaos will erupt */
{ "write-file", "fdw", ALL, write_cmd },
{ "read-file", "Cfdr", ALL, read_cmd },
{ "read-merge", "fer", ALL, read_merge_cmd },
{ "clear-spreadsheet", "C", ALL, kill_all_cmd },
{ "copy-region", "Rf", ALL, copy_region },
{ "copy-values-in_region","Rf", ALL, copy_values_region },
{ "format-region", "rg", ALL, format_area },
{ "move-region", "Rh", ALL, move_region },
{ "print-region", "Fi", ALL, print_region },
{ "sort-region", "tj", ALL, sort_region_cmd },
{ "write-region-to-file", "Fe", ALL, write_reg_cmd },
{ "delete-region", "rk", ALL, delete_region },
{ "start-entering-macro", 0, ALL, start_macro },
{ "execute-command", "tl", ALL, execute_cmd },
{ "macro-interactive-here",0, ALL, interact_macro_cmd },
/* If you change which line goto-cell uses, you *must* modify goto_region() */
{ "goto-cell", "rm", ALL, goto_region },
{ "mark-cell", 0, ALL, mark_cell_cmd },
{ "edit-cell", "T0", ALL|WTH_CHR,do_input_cmd },
{ "edit-value-cell", "T1", ALL|WTH_CHR,do_input_cmd },
{ "format-cell", "T", ALL, format_cell_cmd },
{ "delete-cell", 0, ALL, kill_cell_cmd },
{ "edit-cell-with-default","T3", ALL|WTH_CHR,do_input_cmd },
{ "digit-0", "N", ALL|NC, digit_cmd },
{ "digit-1", "N", ALL|NC, digit_cmd },
{ "digit-2", "N", ALL|NC, digit_cmd },
{ "digit-3", "N", ALL|NC, digit_cmd },
{ "digit-4", "N", ALL|NC, digit_cmd },
{ "digit-5", "N", ALL|NC, digit_cmd },
{ "digit-6", "N", ALL|NC, digit_cmd },
{ "digit-7", "N", ALL|NC, digit_cmd },
{ "digit-8", "N", ALL|NC, digit_cmd },
{ "digit-9", "N", ALL|NC, digit_cmd },
{ "enter-text-in-cell", "T2", WTH_CHR|ALL,do_input_cmd },
{ "show-options", 0, ALL, show_options },
{ "open-window", "tn", ALL, open_window },
{ "close-window", "to", ALL, close_window },
{ "goto-window", "to", ALL, goto_window },
{ "stop-entering-macro", 0, ALL, end_macro },
{ "create-keymap", "ts", ALL, make_keymap },
#ifdef TEST
{ "debug", "tp", ALL, do_debug },
#endif
{ "bound-menu", 0, WTH_CHR|ALL,0 },
{ 0, 0, 0, 0 }
};
#ifdef __TURBOC__
extern void deal_alarm EXT0();
static unsigned char
real_get_chr FUN0()
{
unsigned char ch;
if(auto_recalc) {
current_cycle++;
if(!bkgrnd_recalc) {
while(eval_next_cell())
;
} else {
if(timer_active) {
static int ttick;
int ev = 1;
for(;kbhit()==0;) {
if(ev) {
ev=eval_next_cell();
if(!ev)
redisp();
}
if(ttick++>=signal_ticks) {
deal_alarm();
ttick=0;
ev=1;
}
}
}
while(kbhit()==0 && eval_next_cell())
;
}
}
redisp();
ch=getch();
if(making_macro) {
if(ch==0)
*making_macro++=0x80|'a';
else if(ch=='{')
*making_macro++=0x80|'b';
else
*making_macro++=ch;
if(making_macro>=making_macro_start+making_macro_size) {
making_macro_start=ck_realloc(making_macro_start,5+making_macro_size*2);
making_macro=making_macro_start+making_macro_size;
making_macro_size*=2;
}
}
return ch;
}
#else
#if !defined(SIGIO) || defined(AMIGA)
#undef CTRL(X)
#undef NC
#include <curses.h>
int intr1 = 0;
int intr2 = 0;
static unsigned char
real_get_chr FUN0()
{
static int saved;
unsigned char ret;
if(saved) {
ret=saved-1;
saved=0;
goto fini;
}
if(auto_recalc) {
current_cycle++;
if(!bkgrnd_recalc) {
while(eval_next_cell())
;
} else {
int ev;
do {
#if !defined(AMIGA)
nodelay(stdscr, TRUE);
#endif
while(ev=eval_next_cell())
if((ret=getch())!=ERR)
goto fini;
#ifdef TEST
else
intr1++;
#endif
#if !defined(AMIGA)
nodelay(stdscr,FALSE);
#endif
redisp();
ret=getch();
#ifdef TEST
if(ret==ERR)
intr2++;
#endif
} while(ret==ERR);
goto fini;
}
}
redisp();
ret= getch();
fini:
if(making_macro) {
if(ret==0)
*making_macro++=0x80|'a';
else if(ret=='{')
*making_macro++=0x80|'b';
else
*making_macro++=ret;
if(making_macro>=making_macro_start+making_macro_size) {
making_macro_start=ck_realloc(making_macro_start,5+making_macro_size*2);
making_macro=making_macro_start+making_macro_size;
making_macro_size*=2;
}
}
if(ret&0x80) {
if(ret==0x9b)
{
/* this is a test pass travis */
return 0x9b;
}
saved=1+(ret&0x7f);
return CTRL('[');
}
return ret;
}
#else
#ifdef __STDC__
volatile
#endif
int have_kbd_input = 0;
static char ibuf[100];
static int i_in,i_cnt;
static unsigned char
real_get_chr FUN0()
{
unsigned char ch;
static int save;
if(save) {
ch=save-1;
save=0;
goto fini;
}
if(i_cnt) {
ch=ibuf[i_cnt++];
if(i_cnt==i_in)
i_cnt=i_in=0;
goto fini;
}
for(;;) {
if(auto_recalc) {
current_cycle++;
if(bkgrnd_recalc) {
while(!have_kbd_input && eval_next_cell())
;
} else {
while(eval_next_cell())
;
}
}
redisp();
if(have_kbd_input) {
int ret;
ret=read(0,ibuf,sizeof(ibuf));
if(ret==1) {
have_kbd_input=0;
ch=ibuf[0];
goto fini;
}
if(ret>1) {
if(have_kbd_input<=ret)
have_kbd_input=0;
else
have_kbd_input-=ret;
i_cnt=1;
i_in=ret;
ch=ibuf[0];
goto fini;
}
if(ret==0 || (errno!=EWOULDBLOCK && errno!=EINTR))
return EOF;
}
pause();
}
fini:
if(making_macro) {
if(ch==0)
*making_macro++=0x80|'a';
else if(ch=='{')
*making_macro++=0x80|'b';
else
*making_macro++=ch;
if(making_macro>=making_macro_start+making_macro_size) {
making_macro_start=ck_realloc(making_macro_start,5+making_macro_size*2);
making_macro=making_macro_start+making_macro_size;
making_macro_size*=2;
}
}
if(ch&0x80) {
save=1+(ch&0x7f);
ch=CTRL('[');
}
return ch;
}
void
got_sigio FUN1(int,sig)
{
have_kbd_input++;
}
#endif
#endif
#ifdef TEST
extern int yydebug;
int debug;
int dbg_do_stderr;
extern void dbg_print_ref_fm();
static void
dbg_show_var FUN2(char *,name, struct var *,v)
{
char *ptr;
/* if(*cmd && strncmp(cmd,v->var_name,strlen(cmd)))
continue; */
if(v->var_flags==VAR_UNDEF)
ptr="Undefined";
else if(v->var_flags==VAR_CELL)
ptr="Cell";
else if(v->var_flags==VAR_RANGE)
ptr="Range";
else
ptr="*UNKNOWN*";
text_line("%s %s %s ",v->var_name,ptr,range_name(&(v->v_rng)));
if(!v->var_ref_fm)
text_line("no refs");
else
dbg_print_ref_fm(v->var_ref_fm);
}
/* Debugging is very important. That's why there is an entire function to
handle it. . . :-)
*/
static void
do_debug FUN1(char *,cmd)
{
CELL *cp;
char *ptr;
FILE *output;
extern struct ref_fm *timer_cells;
extern struct rng all_rng;
extern void dbg_print_ref_to();
extern void dbg_print_formula();
extern void dbg_print_cell EXT1(CELL *);
extern void dbg_print_cols EXT1(CELLREF);
extern void dbg_print_rows EXT0();
extern void dbg_print_array EXT0();
extern void ref_stats EXT0();
extern int fputs();
extern void text_start();
extern void text_finish();
output=stdout;
ptr=cmd;
switch(*ptr++) {
case 'd':
debug=astol(&ptr);
info_msg("Debug now %d",debug);
return;
case 'f':
while(*ptr==' ')
ptr++;
freopen(ptr,"w",stderr);
dbg_do_stderr=0;
return;
case 'y':
yydebug= !yydebug;
return;
case 'E':
output=stderr;
break;
default:
break;
}
--ptr;
text_start();
switch(*ptr++) {
CELLREF rr,cc;
int n;
int todo;
struct rng rn;
default:
print_buf[0]='\0';
break;
case 'R':
dbg_print_rows();
break;
case 'C':
n=astol(&ptr);
dbg_print_cols(n);
break;
case 'p':
dbg_print_array();
break;
case 'S':
ref_stats();
break;
case 'r':
todo= *ptr++;
if(!*ptr)
find_cells_in_range(&all_rng);
else {
get_abs_rng(&ptr,&rn);
find_cells_in_range(&rn);
}
ptr=print_buf;
while(cp=next_row_col_in_range(&rr,&cc)) {
text_line("(r%uc%u)",rr,cc);
if(todo=='f' && cp->cell_refs_from) {
dbg_print_ref_fm(cp->cell_refs_from);
} else if(todo=='t' && cp->cell_refs_to) {
dbg_print_ref_to(cp->cell_refs_to,cp->cell_formula);
} else if(todo=='c') {
dbg_print_cell(cp);
} else if(todo=='e' && cp->cell_formula) {
dbg_print_formula(cp);
} else if(todo=='F') {
text_line("flags %#x cycle %d",cp->cell_flags,cp->cell_cycle);
}
}
break;
case 't':
#ifdef hp800
{
sigset_t sigs;
sigprocmask(0,(void *)0,&sigs);
text_line("Timer is %sactive, ticks=%lu (%lu), sigs %x.%x.%x.%x.%x.%x.%x.%x",timer_active ? "" : "not ",signal_ticks,signal_ticks/TIMER_MULT,sigs.sigset[0],sigs.sigset[1],sigs.sigset[2],sigs.sigset[3],sigs.sigset[4],sigs.sigset[5],sigs.sigset[6],sigs.sigset[7]);
dbg_print_ref_fm(timer_cells);
}
#else
text_line("Timer is %sactive, ticks=%lu (%lu)",timer_active ? "" : "not ",signal_ticks,signal_ticks/TIMER_MULT);
dbg_print_ref_fm(timer_cells);
#endif
break;
case 'v':
while(*ptr==' ')
ptr++;
cmd=ptr;
for_all_vars(dbg_show_var);
break;
case 'm':
if(*ptr)
desc_map(the_maps[atoi(ptr)]);
break;
case 'w':
dbg_show_wins();
break;
#if defined(SIGIO) && !defined(AMIGA)
case 'k':
text_line("i_in %d i_cnt %d have_input %d",i_in,i_cnt,have_kbd_input);
break;
#endif
}
text_finish();
}
#endif
void
init_maps FUN0()
{
static char main_name[] = "main";
static char meta_name[] = "meta";
static char edit_name[] = "edit";
static char em_name[] = "edit-meta";
static char ansi_name[] = "ansi";
static char digit_name[] = "digit";
extern struct keymap edit_map[];
extern struct keymap edit_meta_map[];
extern struct cmd_func edit_funcs[];
the_maps=ck_malloc(sizeof(struct keymap *)*6);
map_names=ck_malloc(sizeof(char *)*6);
num_maps=6;
the_maps[0]= &main_map[0];
the_maps[1]= &meta_map[0];
the_maps[2]= &edit_map[0];
the_maps[3]= &edit_meta_map[0];
the_maps[4]= &ansi_map;
the_maps[5]= &digit_map;
map_names[0]=main_name;
map_names[1]=meta_name;
map_names[2]=edit_name;
map_names[3]=em_name;
map_names[4]=ansi_name;
map_names[5]=digit_name;
the_funcs=ck_malloc(sizeof(struct cmd_func *)*2);
num_funcs=2;
the_funcs[0]= &cmd_funcs[0];
the_funcs[1]= &edit_funcs[0];
}
static int add_usr_cmds FUN1(struct cmd_func *, new_cmds)
{
num_funcs++;
the_funcs=ck_realloc(the_funcs,num_funcs*sizeof(struct cmd_func *));
the_funcs[num_funcs-1]=new_cmds;
return num_funcs-1;
}
#ifdef USE_DLD
static int add_usr_maps FUN1(struct keymap **, new_maps)
{
int n;
for(n=1;new_maps[n];n++)
;
the_maps=ck_realloc(the_maps,(n+num_maps)*sizeof(struct keymap *));
bcopy(new_maps, &the_maps[num_maps],n*sizeof(struct keymap *));
num_maps+=n;
return num_maps-n;
}
#endif
int
main FUN2(int,argc, char **,argv)
{
int c;
int num;
void got_sig();
myname=argv[0];
__make_backups=1;
#if !defined(__TURBOC__) && !defined(SYSV)
setbuffer(stdout,buf,sizeof(buf));
#endif
if(argc<2 || strcmp(argv[1],"-q")) {
if(!getenv("OLEO")) {
fprintf(stdout,"Oleo version 0.03.2, Copyright (C) 1990 Free Software Foundation, Inc.\n");
fprintf(stdout,"There is ABSOLUTELY NO WARRANTY for Oleo; see the file COPYING\n");
fprintf(stdout,"for details. Oleo is free software and you are welcome to distribute\n");
fprintf(stdout,"copies of it under certain conditions; see the file COPYING to see the\n");
fprintf(stdout,"conditions.\n\n");
fflush(stdout);
sleep(5);
}
} else {
--argc;
++argv;
}
init_mem();
init_eval();
init_refs();
init_cells();
init_maps();
obstack_init(¯o_stack);
c=0;
if(argc>2 && !strcmp(argv[1],"-f")) {
--argc;
++argv;
c++;
}
open_display(c);
if(argc>2) {
fprintf(stderr,"Usage: %s [filename]\n",argv[0]);
exit(1);
}
#ifdef USE_DLD
if(!index(myname,'/')) {
char *name;
name=dld_find_executable(myname);
num=dld_init(name);
free(name);
} else
num=dld_init(myname);
if(num)
error_msg("dld_init() failed: %s",(dld_errno < 0 || dld_errno > dld_nerr) ? "Unknown error" : dld_errlst[dld_errno]);
dld_search_path=":/usr/local/lib/oleo:/lib:/usr/lib:/usr/local/lib";
#endif
{
FILE *fp;
extern int fclose();
char *ptr,*home;
/* would be nice to use ck_fopen, but these files might not
exist. . . */
home=getenv("HOME");
if(home) {
ptr=mk_sprintf("%s/%s",home,RCFILE);
if(fp=fopen(ptr,"r")) {
read_cmds_cmd(fp);
fclose(fp);
}
free(ptr);
}
if(fp=fopen(RCFILE,"r")) {
read_cmds_cmd(fp);
fclose(fp);
}
if(argc==2) {
set_line(&in_line[3],argv[1]);
if(fp=fopen(argv[1],"r")) {
(*read_file)(fp,0);
fclose(fp);
} else
error_msg("Can't open %s: %s",argv[1],err_msg());
}
}
signal(SIGINT,got_sigint);
#ifdef SIGQUIT
signal(SIGQUIT,got_sig);
signal(SIGILL,got_sig);
signal(SIGEMT,got_sig);
signal(SIGBUS,got_sig);
signal(SIGSEGV,got_sig);
signal(SIGPIPE,got_sig);
#endif
#if defined(SIGIO) && !defined(AMIGA)
signal(SIGIO,got_sigio);
/* close(0);
if(open("/dev/tty",0)!=0) {
fprintf(stderr,"Didn't get 0 when trying to re-open stdin\n");
exit(1);
} */
#ifdef FASYNC
term_flag=fcntl(0,F_GETFL,FASYNC /* |FNDELAY */);
c=fcntl(0,F_SETFL,FASYNC /* |FNDELAY */);
if(c==-1) {
fprintf(stderr,"Can't turn on FASYNC|FNDELAY on stdin: %s\n",err_msg());
exit(1);
}
#else
#ifdef FIOSSAIOSTAT
{
int i;
ioctl(0,FIOGSAIOSTAT,&i);
term_flag=i;
ioctl(0,FIOGNBIO, &i);
if(i)
term_flag+=2;
i=1;
ioctl(0,FIOSSAIOSTAT,&i);
/* ioctl(0,FIOSNBIO,&i); */
i=getpid();
ioctl(0,FIOSSAIOOWN,&i);
}
#endif
#endif
#endif
recenter_cur_win();
for(;;) {
if(how_many!=1) {
how_many=1;
cur_status();
}
clear_top_before();
map_chr(MAIN_MAP);
if(topclear && !rmac)
clear_top_after();
swtch:
if(!cur_cmd) {
error_msg("That key is unbound");
continue;
}
if((cur_cmd->func_flags&NONTOP)==0) {
error_msg("Command '%s' is not appropriate now.",cur_cmd->func_name);
continue;
}
num=global_cmd(MAIN_MAP);
if(num==-2)
error_msg("Command '%s' is *not* appropriate now.",cur_cmd->func_name);
else if(num>=0) {
c=num;
goto swtch;
}
}
}
static FILE *
open_file FUN3(char *,prompt, struct line *,line, char *,mode)
{
FILE *fp;
if(get_inp_line(prompt,line))
return 0;
if((fp=xopen_with_backup(line->buf,mode))==0) {
error_msg("Can't open file '%s':%s",line->buf,err_msg());
return 0;
}
return fp;
}
static void
close_file FUN2(struct line *,line, FILE *,fp)
{
int num;
if(num=xclose(fp))
error_msg("Can't close '%s': Error code %d: %s",line->buf,num,err_msg());
}
/* Deal with point-n-shoot */
static int
get_a_range FUN3(char *,whatfor, struct rng *,r, struct line *,line)
{
char *ptr;
if(mkrow!=NON_ROW) {
/* The range has already been selected */
got_rng:
set_rng(r,mkrow,mkcol,curow,cucol);
mkrow=NON_ROW;
return 0;
}
switch(get_inp_line(whatfor,line)) {
case 0:
if(mkrow!=NON_ROW)
goto got_rng;
ptr=line->buf;
if(get_abs_rng(&ptr,r) || *ptr!='\0') {
error_msg("Can't parse '%s'",line->buf);
return 1;
}
return 0;
case 1:
if(mkrow!=NON_ROW)
goto got_rng;
return 1;
case 2:
return 1;
#ifdef TEST
default:
panic("Get_inp_line() what?");
#endif
}
return 1;
}
static FILE *
get_range_and_file FUN3(char *,whatfor, struct rng *,r, struct line *,line)
{
char *ptr;
char *prompt;
int got_rng = 0;
FILE *ret;
extern char *strdup();
if(mkrow!=NON_ROW) {
/* We've got the range, just get the file */
set_rng(r,mkrow,mkcol,curow,cucol);
got_rng++;
mkrow=NON_ROW;
prompt=mk_sprintf("%s %s to file",whatfor,range_name(r));
} else
prompt=strdup(whatfor);
if(get_inp_line(prompt,line)) {
free(prompt);
return 0;
}
free(prompt);
if(mkrow!=NON_ROW) {
if(got_rng) {
error_msg("Two ranges?");
return 0;
}
set_rng(r,mkrow,mkcol,curow,cucol);
mkrow=NON_ROW;
got_rng++;
}
ptr=line->buf;
if(!got_rng) {
if(get_abs_rng(&ptr,r)) {
error_msg("Can't parse '%s'",line->buf);
return 0;
}
if(*ptr==',')
ptr++;
}
while(*ptr==' ')
ptr++;
if(!*ptr)
return 0;
ret=xopen_with_backup(ptr,"w");
if(!ret)
error_msg("Can't open file '%s':%s",ptr,err_msg());
return ret;
}
static int
get_two_ranges FUN4(char *,whatfor, struct rng *,one, struct rng *,two, struct line *,line)
{
char *ptr;
char *prompt;
int num_got = 0;
int n;
prompt=0;
if(mkrow!=NON_ROW) {
/* We've got the first one already */
set_rng(one,mkrow,mkcol,curow,cucol);
mkrow=NON_ROW;
num_got++;
}
while(num_got!=2) {
prompt = (num_got==1) ? mk_sprintf("%s %s to",whatfor,range_name(one)) : whatfor;
n=get_inp_line(prompt,line);
if(prompt!=whatfor)
free(prompt);
if(n>1 || (n==1 && mkrow==NON_ROW))
return 1;
if(mkrow!=NON_ROW) {
if(line->buf[0]) {
error_msg(num_got ? "Extra characters '%s'" : "'%s' is ambiguous", line->buf);
return 1;
}
set_rng(num_got ? two : one, mkrow,mkcol,curow,cucol);
mkrow=NON_ROW;
num_got++;
} else {
ptr=line->buf;
if(!num_got) {
if(get_abs_rng(&ptr,one)) {
error_msg("Can't parse first range in '%s'",line->buf);
return 1;
}
if(*ptr==',')
ptr++;
}
if(get_abs_rng(&ptr,two)) {
if(num_got) {
error_msg("Can't find second range in '%s'",line->buf);
return 1;
}
num_got++;
} else if(!num_got)
num_got+=2;
else
num_got++;
}
}
if(*ptr) {
error_msg("Extra characters in '%s'",line->buf);
return 1;
}
sprint_line(line,"%s %s",range_name(one),range_name(two));
return 0;
}
/* Read a character. If we're in a macro, read from the macro. . . */
int
get_chr FUN0()
{
unsigned int ch;
#ifdef TEST
extern CELL *my_cell;
if(my_cell)
error_msg("Something didn't clear my_cell!");
#endif
if(rmac) {
ch= *(rmac->mac_exe++);
switch(ch) {
case '{': /* What else can we do? */
case '\0':
--(rmac->mac_exe);
break;
case (0x80|'a'):
ch=0;
break;
case (0x80|'b'):
ch='{';
break;
default:
break;
}
} else
ch=real_get_chr();
return ch;
}
void
map_chr FUN1(int, map)
{
unsigned int ch;
struct keymap *keymap;
struct key *key;
#ifdef TEST
extern CELL *my_cell;
if(my_cell)
error_msg("Something didn't clear my_cell!");
#endif
keymap= the_maps[map];
for(;;) {
/* ch=get_chr(); */
if(rmac) {
int len;
unsigned char *ptr;
tryagain:
ch= *(rmac->mac_exe++);
switch(ch) {
case '\0':
cur_vector=0;
cur_cmd= &cmd_funcs[END_MACRO];
cur_chr=0;
return;
case 0x80|'a':
ch='\0';
break;
case 0x80|'b':
ch='{';
break;
case '{':
for(ptr=rmac->mac_exe;*ptr && *ptr!=' ' && *ptr!='}';ptr++)
;
len=ptr-rmac->mac_exe;
for(cur_vector=0;cur_vector<num_funcs;cur_vector++)
for(cur_cmd= &the_funcs[cur_vector][0];cur_cmd->func_name;cur_cmd++)
if(!strincmp((char *)(rmac->mac_exe),cur_cmd->func_name,len) && cur_cmd->func_name[len]=='\0') {
cur_chr='\0';
goto out;
}
error_msg("Ignoring unknown function '%.*s' in macro",len,rmac->mac_exe);
while(*ptr!='\0' && *ptr!='}')
ptr++;
if(*ptr=='}')
ptr++;
rmac->mac_exe=ptr;
goto tryagain;
out:
if(*ptr==' ') {
/* ... add argument support here ... */
if(!cur_cmd->func_args) {
error_msg("Ignoring extra operand to %s",cur_cmd->func_name);
while(*ptr && *ptr!='}')
ptr++;
if(*ptr=='}')
ptr++;
} else if(cur_cmd->func_args[0]=='n') {
how_many=astol((char **)(&ptr));
if(*ptr=='}')
ptr++;
} else {
macro_func_arg=(char *)ptr;
while(*ptr && *ptr!='}')
ptr++;
if(*ptr=='}')
*ptr++='\0';
}
rmac->mac_exe=ptr;
} else
rmac->mac_exe+=len+1;
return;
}
} else
ch=real_get_chr();
for(;;) {
if(ch>=keymap->lochr && ch<=keymap->hichr) {
key= keymap->map_dense ? keymap->keys : &(keymap->keys[ch-keymap->lochr]);
if(key->vector==255) {
keymap=the_maps[key->code];
break;
}
if(key->vector!=0 || key->code!=0) {
cur_vector=key->vector;
cur_cmd= &(the_funcs[key->vector][key->code]);
cur_chr=ch;
return;
}
}
if (!(keymap=keymap->map_next)) {
/* Searched through all the keymaps, and didn't find a match */
cur_vector=0;
cur_cmd=0;
cur_chr=ch;
return;
}
}
}
}
/* Return values:
-3 break key!
-2 c is inappropriate
-1 C is OK
0+ New char value is ret-1;
*/
int
global_cmd FUN1(int,magic)
{
char *ptr;
struct rng fm,to;
FILE *fp;
static struct line confirm;
struct cmd_func *cmd;
if(!cur_cmd)
return -2;
cmd=cur_cmd;
if(cmd->func_args) {
ptr=cmd->func_args;
next_arg:
switch(*ptr++) {
case 'R':
if(get_two_ranges(cmd->func_name,&fm,&to,&in_line[*ptr++-'a']))
break;
(*cmd->func_func)(&fm,&to);
break;
case 'r':
if(get_a_range(cmd->func_name,&to,&in_line[*ptr++-'a']))
break;
(*cmd->func_func)(&to);
break;
case 't':
if(get_inp_line(cmd->func_name,&in_line[*ptr++-'a']))
break;
(*cmd->func_func)(in_line[cmd->func_args[1]-'a'].buf);
break;
case 'C':
if(modified==0)
goto next_arg;
set_line(&confirm,0);
if( get_inp_line("Are you SURE",&confirm)
|| (confirm.buf[0]!='Y' && confirm.buf[0]!='y'))
return -1;
goto next_arg;
case 'f':
fp=open_file(cmd->func_name,&in_line[*ptr-'a'],ptr+1);
if(!fp)
break;
(*cmd->func_func)(fp);
close_file(&in_line[*ptr++-'a'],fp);
break;
case 'F':
fp=get_range_and_file(cmd->func_name,&to,&in_line[*ptr-'a']);
if(!fp)
break;
(*cmd->func_func)(fp,&to);
close_file(&in_line[*ptr++-'a'],fp);
break;
case 'n':
if(!*ptr)
(*cmd->func_func)();
else if(*ptr>='0' && *ptr<='9')
(*cmd->func_func)(*ptr-'0');
else if(*ptr>='a' && *ptr<='z')
(*cmd->func_func)((*ptr-'a')*26+ptr[1]-'a');
else
(*cmd->func_func)();
break;
case 'T':
if(*ptr>='0' && *ptr<='9')
(*cmd->func_func)(*ptr-'0',cur_chr);
else
(*cmd->func_func)();
break;
case 'N':
(*cmd->func_func)(magic);
return cur_chr;
case '\0':
(*cmd->func_func)();
break;
#ifdef TEST
default:
panic("Unknown arg type %s in global_cmd",ptr);
#endif
}
if(cmd->func_flags&BRK)
return -3;
return -1;
} else if(cmd->func_func) {
if(cmd->func_flags&WTH_CHR)
(*cmd->func_func)(cur_chr);
else
(*cmd->func_func)();
if(cmd->func_flags&BRK)
return -3;
return -1;
}
return -2;
}
static void
write_keys_cmd FUN1(FILE *,fp)
{
struct keymap *map;
int n;
int key;
int vec;
int code;
for(n=0;n<num_maps;n++) {
char *def;
for(map=the_maps[n];map && !map->map_end;map=map->map_next)
;
def=0;
if(map && map->map_next) {
for(key=0;key<num_maps;key++)
if(the_maps[key]==map->map_next) {
def=map_names[key];
break;
}
}
if(def)
fprintf(fp,"create-keymap %s %s\n",map_names[n],def);
else
fprintf(fp,"create-keymap %s\n",map_names[n]);
}
for(n=0;n<num_maps;n++) {
for(map=the_maps[n];map;map=map->map_next) {
for(key=map->lochr;key<=map->hichr;key++) {
if(map->map_dense) {
vec=map->keys[0].vector;
code=map->keys[0].code;
} else {
vec=map->keys[key-map->lochr].vector;
code=map->keys[key-map->lochr].code;
}
if(vec==255)
fprintf(fp,"bind-key %s %s %s\n",
map_names[n],
map_names[code],
char_to_string(key));
else if(vec || code)
fprintf(fp,"bind-key %s %s %s\n",
map_names[n],
the_funcs[vec][code].func_name,
char_to_string(key));
}
if(map->map_end)
map=0;
}
}
}
static void
clear_keymap FUN1(struct keymap *,m)
{
int n;
while(m) {
if(m->map_malloc) {
if(m->map_dense) {
m->keys[0].vector=0;
m->keys[0].code=0;
m->hichr=m->lochr;
} else {
for(n=0;n<=m->hichr-m->lochr;n++) {
m->keys[n].vector=0;
m->keys[n].code=0;
}
}
} else {
m->keys=ck_malloc(sizeof(struct key)*(1+m->hichr-m->lochr));
for(n=0;n<=m->hichr-m->lochr;n++) {
m->keys[n].vector=0;
m->keys[n].code=0;
}
m->map_malloc=2;
}
if(m->map_end)
break;
m=m->map_next;
}
}
static void
make_keymap FUN1(char *,mapname)
{
char *ptr;
int num;
struct keymap *linkmap;
extern char *strdup();
for(ptr=mapname;*ptr && *ptr!=' ';ptr++)
;
linkmap=0;
if(*ptr) {
*ptr++='\0';
for(num=0;num<num_maps;num++) {
if(!strcmp(map_names[num],ptr)) {
linkmap=the_maps[num];
break;
}
}
}
for(num=0;num<num_maps;num++) {
if(!strcmp(map_names[num],mapname)) {
clear_keymap(the_maps[num]);
return;
}
}
the_maps=ck_realloc(the_maps,(num_maps+1)*sizeof(struct keymap *));
the_maps[num_maps]=ck_malloc(sizeof(struct keymap));
the_maps[num_maps]->map_next=linkmap;
the_maps[num_maps]->map_end=1;
the_maps[num_maps]->map_dense=1;
the_maps[num_maps]->lochr='\0';
the_maps[num_maps]->hichr='\0';
the_maps[num_maps]->keys=ck_malloc(sizeof(struct key));
the_maps[num_maps]->keys[0].vector=0;
the_maps[num_maps]->keys[0].code=0;
map_names=ck_realloc(map_names,(num_maps+1)*sizeof(char *));
map_names[num_maps]=strdup(mapname);
num_maps++;
}
static void
read_cmds_cmd FUN1(FILE *,fp)
{
char *ptr;
while(fgets(print_buf,300,fp)) {
if(ptr=rindex(print_buf,'\n'))
*ptr='\0';
execute_cmd(print_buf);
}
}
static void
write_cmd FUN1(FILE *,fp)
{
(*write_file)(fp,0);
modified=0;
}
static void
read_cmd FUN1(FILE *,fp)
{
(*read_file)(fp,0);
}
static void
read_merge_cmd FUN1(FILE *,fp)
{
(*read_file)(fp,1);
}
static void
write_reg_cmd FUN2(FILE *,fp,struct rng *,rng)
{
(*write_file)(fp,rng);
}
static void
sort_region_cmd FUN1(char *,ptr)
{
struct cmp {
char mult;
CELLREF row;
CELLREF col;
};
struct rng tmp_rng;
extern struct rng sort_rng;
extern struct rng sort_ele;
extern struct cmp *sort_keys;
extern int sort_keys_num;
extern int sort_keys_alloc;
extern void sort_region EXT0();
if(get_abs_rng(&ptr,&sort_rng)) {
error_msg("Can't find a range to sort in %s", ptr);
return;
}
cur_row=sort_rng.lr;
cur_col=sort_rng.lc;
while(*ptr==' ')
ptr++;
if(!*ptr) {
sort_ele.lr=0;
sort_ele.lc=0;
sort_ele.hr=0;
sort_ele.hc=0;
} else if(!parse_cell_or_range(&ptr,&sort_ele)) {
error_msg("Can't parse elements in %s",ptr);
return;
} else {
sort_ele.lr-=sort_rng.lr;
sort_ele.lc-=sort_rng.lc;
sort_ele.hr-=sort_rng.lr;
sort_ele.hc-=sort_rng.lc;
}
sort_keys_num=0;
while(*ptr==' ')
ptr++;
for(;*ptr;) {
if(sort_keys_num==sort_keys_alloc) {
sort_keys_alloc++;
if(sort_keys_alloc>1)
{
sort_keys=ck_realloc(sort_keys,sort_keys_alloc*sizeof(struct cmp));
}
else
sort_keys=ck_malloc(sizeof(struct cmp));
}
sort_keys[sort_keys_num].mult=1;
if(*ptr=='+')
ptr++;
else if(*ptr=='-') {
sort_keys[sort_keys_num].mult= -1;
ptr++;
}
if(!*ptr) {
sort_keys[sort_keys_num].row=0;
sort_keys[sort_keys_num].col=0;
sort_keys_num++;
break;
}
if(!parse_cell_or_range(&ptr,&tmp_rng) || tmp_rng.lr!=tmp_rng.hr || tmp_rng.lc!=tmp_rng.hc) {
error_msg("Can't parse key #%d in %s",sort_keys_num+1,ptr);
sort_keys_num= -1;
return;
}
sort_keys[sort_keys_num].row=tmp_rng.lr - sort_rng.lr;
sort_keys[sort_keys_num].col=tmp_rng.lc - sort_rng.lc;
sort_keys_num++;
while(*ptr==' ')
ptr++;
}
if(sort_keys_num==0) {
if(sort_keys_alloc==0) {
sort_keys_alloc++;
sort_keys=ck_malloc(sizeof(struct cmp));
}
sort_keys[0].mult=1;
sort_keys[0].row=0;
sort_keys[0].col=0;
sort_keys_num++;
}
sort_region();
disp_scrn();
}
static void
set_var FUN1(char *,ptr)
{
int num;
char *ret;
extern char *new_var_value EXT3(char *, int, char *);
while(*ptr==' ')
ptr++;
for(num=0;ptr[num] && ptr[num]!=' ';num++)
;
modified=1;
if(!ptr[num])
ret=new_var_value(ptr,num,(char *)0);
else
ret=new_var_value(ptr,num,&ptr[num+1]);
if(ret)
error_msg("Can't set-variable %s: %s\n",ptr,ret);
}
static void
show_var FUN1(char *,ptr)
{
struct var *v;
int num;
while(*ptr==' ')
ptr++;
for(num=0;ptr[num] && ptr[num]!=' ';num++)
;
v=find_var(ptr,num);
if(!v || v->var_flags==VAR_UNDEF) {
error_msg("There is no '%s'",ptr);
return;
}
#ifdef A0_REFS
if(v->v_rng.lr!=v->v_rng.hr || v->v_rng.lc!=v->v_rng.hc)
/* FOO */sprintf(print_buf,"%s $%s$%u:$%s$%u",v->var_name,col_to_str(v->v_rng.lc),v->v_rng.lr,col_to_str(v->v_rng.hc),v->v_rng.hr);
else
/* FOO */sprintf(print_buf,"%s $%s$%u",v->var_name,col_to_str(v->v_rng.lc),v->v_rng.lr);
#else
sprintf(print_buf,"%s %s",v->var_name,range_name(&(v->v_rng)));
#endif
info_msg(print_buf);
set_line(&in_line[1],print_buf);
}
static void
show_a_var FUN2(char *,name, struct var *,v)
{
if(v->var_flags==VAR_UNDEF)
return;
#ifdef A0_REFS
if(v->v_rng.lr!=v->v_rng.hr || v->v_rng.lc!=v->v_rng.hc)
/* FOO */text_line("%-20s $%s$%u:$%s$%u",v->var_name,col_to_str(v->v_rng.lc),v->v_rng.lr,col_to_str(v->v_rng.hc),v->v_rng.hr);
else
/* FOO */text_line("%-20s $%s$%u",v->var_name,col_to_str(v->v_rng.lc),v->v_rng.lr);
#else
text_line("%-20s %s",v->var_name,range_name(&(v->v_rng)));
#endif
}
static void
show_all_var FUN0()
{
extern void text_start EXT0();
extern void text_finish EXT0();
text_start();
for_all_vars(show_a_var);
text_finish();
}
static void
shift_cell_cursor FUN1(int, dirn)
{
CELLREF c;
int w = 0;
int over,down;
over=colmagic[dirn]*how_many;
down=rowmagic[dirn]*how_many;
if(over>0) {
c=cucol;
while(c<MAX_COL && over-->0) {
c++;
while((w=get_width(c))==0 && c<MAX_COL)
c++;
}
if(over>0 || c==cucol || w==0) {
error_msg("Can't go right");
return;
}
} else if(over<0) {
c=cucol;
while(c>MIN_COL && over++<0) {
--c;
while((w=get_width(c))==0 && c>MIN_COL)
--c;
}
if(over<0 || c==cucol || w==0) {
error_msg("Can't go left");
return;
}
} else
c = cucol;
if(down>0) {
if(curow>MAX_ROW-down) {
error_msg("Can't go down");
return;
}
} else if(down<0) {
if(curow<MIN_ROW-down) {
error_msg("Can't go up");
return;
}
}
move_cell_cursor(curow+down,c);
}
static void
scan_cell_cursor FUN1(int,magic)
{
CELLREF pos,pos_end,pos_inc;
CELL *cp;
int over,down;
extern CELLREF max_row(),max_col();
over=colmagic[magic]*how_many;
down=rowmagic[magic]*how_many;
if(over) {
if(over>0) {
pos=max_col(curow);
pos_end=MIN_COL;
pos_inc= -1;
} else {
pos=MIN_COL;
pos_end=max_col(curow);
pos_inc=1;
}
for(;;) {
for(;((!(cp=find_cell(curow,pos)) || !GET_TYP(cp)));pos+=pos_inc) {
if(pos==pos_end) {
how_many=1;
pos=MIN_COL;
break;
}
}
if(--how_many==0)
break;
pos+=pos_inc;
}
move_cell_cursor(curow,pos);
} else {
if(down>0) {
pos=max_row(cucol);
pos_end=MIN_ROW;
pos_inc= -1;
} else {
pos=MIN_ROW;
pos_end=max_row(cucol);
pos_inc=1;
}
for(;;) {
for(;(!(cp=find_cell(pos,cucol)) || !GET_TYP(cp));pos+=pos_inc) {
if(pos==pos_end) {
how_many=1;
pos=MIN_ROW;
break;
}
}
if(--how_many==0)
break;
pos+=pos_inc;
}
move_cell_cursor(pos,cucol);
}
}
char *
fmt_to_str FUN1(int, fmt)
{
char *ptr;
static char buf[30];
char nbuf[10];
if(fmt==FMT_DEF)
return "default";
if(fmt==FMT_HID)
return "hidden";
if(fmt==FMT_GPH)
return "graph";
if((fmt&PRC_FLT)==PRC_FLT)
strcpy(nbuf,"float");
else
sprintf(nbuf,"%d",(fmt&PRC_FLT));
switch(fmt|PRC_FLT) {
case FMT_USR:
ptr="user-";
sprintf(nbuf,"%d",(fmt&PRC_FLT)+1);
break;
case FMT_GEN:
ptr="general.";
break;
case FMT_DOL:
ptr="dollar.";
break;
case FMT_CMA:
ptr="comma.";
break;
case FMT_PCT:
ptr="percent.";
break;
case FMT_FXT:
if((fmt&PRC_FLT)==0)
return "integer";
if(fmt==FMT_FXT)
return "decimal";
ptr="fixed.";
break;
case FMT_EXP:
ptr="exponent.";
break;
default:
error_msg("Unknown format %d (%x)",fmt,fmt);
ptr="UNKNOWN";
break;
}
sprintf(buf,"%s%s",ptr,nbuf);
return buf;
}
struct fmt {
int fmt;
char **strs;
};
static char *def_names[] = {"default","def","D",0};
static char *hid_names[] = {"hidden","hid","H",0};
static char *gph_names[] = {"graph","gph","*",0};
static char *int_names[] = {"integer","int","I",0};
static char *dec_names[] = {"decimal","dec",0};
static struct fmt simple[] = {
{ FMT_DEF, def_names },
{ FMT_HID, hid_names },
{ FMT_GPH, gph_names },
{ FMT_FXT-PRC_FLT, int_names },
{ FMT_FXT, dec_names },
{ 0, 0}
};
char *gen_names[] = {"general.","gen.","G",0};
char *dol_names[] = {"dollar.","dol.","$",0};
char *cma_names[] = {"comma.","com.",",",0};
char *pct_names[] = {"percent.","pct.","%",0};
char *fxt_names[] = {"fixed.","fxt.","F",0};
char *exp_names[] = {"exponent.","exp.","E",0};
static struct fmt withprec[] = {
{ FMT_GEN-PRC_FLT, gen_names },
{ FMT_DOL-PRC_FLT, dol_names },
{ FMT_CMA-PRC_FLT, cma_names },
{ FMT_PCT-PRC_FLT, pct_names },
{ FMT_FXT-PRC_FLT, fxt_names },
{ FMT_EXP-PRC_FLT, exp_names },
{ 0, 0 }
};
static int
str_to_fmt FUN1(char *,ptr)
{
struct fmt *f;
char **strs;
int n;
int ret;
char *p1,*p2;
for(f=simple;f->strs;f++) {
for(strs=f->strs;*strs;strs++) {
if(*ptr!=**strs)
continue;
for(p1=ptr,p2= *strs;*p1==*p2 && *p1;p1++,p2++)
;
if(*p1=='\0' && *p2=='\0')
return f->fmt;
}
}
if(!strncmp(ptr,"user-",5)) {
ptr+=5;
n=astol(&ptr);
if(*ptr || n<1 || n>16)
return -1;
return n-1-PRC_FLT+FMT_USR;
}
for(f=withprec,ret=0;!ret && f->strs;f++) {
for(strs=f->strs;*strs;strs++) {
if(*ptr!=**strs)
continue;
for(p1=ptr,p2= *strs;*p2 && *p1==*p2;p1++,p2++)
;
if(!*p2) {
ret=f->fmt;
ptr=p1;
break;
}
}
}
if(!ret || !*ptr)
return -1;
if(!strcmp(ptr,"float") || !strcmp(ptr,"f")) {
n=PRC_FLT;
} else {
n=astol(&ptr);
if(*ptr || n<0 || n>14)
return -1;
}
return ret+n;
}
char *
jst_to_str FUN1(int, jst)
{
if(jst==JST_DEF)
return "default";
if(jst==JST_LFT)
return "left";
if(jst==JST_RGT)
return "right";
if(jst==JST_CNT)
return "center";
return "unknown";
}
static int
chr_to_jst FUN1(int, chr)
{
if(chr=='d' || chr=='D')
return JST_DEF;
if(chr=='l' || chr=='L')
return JST_LFT;
if(chr=='r' || chr=='R')
return JST_RGT;
if(chr=='c' || chr=='C')
return JST_CNT;
return -1;
}
/* parse a range, then turn it into an absolute rng */
static int
get_abs_rng FUN2(char **,pptr, struct rng *,retp)
{
unsigned char n;
while(**pptr==' ')
(*pptr)++;
if(!**pptr)
return 1;
cur_row=curow;
cur_col=cucol;
n=parse_cell_or_range(pptr,retp);
if(!n) {
struct var *v;
char *ptr;
ptr= *pptr;
while(ptr[n] && ptr[n]!=' ')
n++;
v=find_var(ptr,n);
if(!v)
return 1;
(*pptr)+=n;
*retp= v->v_rng;
}
return 0;
}
static void desc_map FUN1(struct keymap *,map)
{
int n;
int maxn;
text_start();
while(map) {
maxn=1+map->hichr-map->lochr;
if(map->map_dense)
text_line("%s - %s: %d %d %s",
char_to_string(map->lochr),
char_to_string(map->hichr),
map->keys[0].vector,
map->keys[0].code,
map->keys[0].vector==255 ? "vector" : the_funcs[map->keys[0].vector][map->keys[0].code].func_name);
else
for(n=0;n<maxn;n++)
text_line("%s: %d %d %s",
char_to_string(map->lochr+n),
map->keys[n].vector,
map->keys[n].code,
map->keys[n].vector==255 ? "vector" : the_funcs[map->keys[n].vector][map->keys[n].code].func_name);
map=map->map_end ? 0 : map->map_next;
}
text_finish();
}
#if 0
static char *
key_name FUN1(int,key)
{
/* int mac;
if(main_map[key]==BOUND_MACRO) {
for(mac=0;mac<n_bound_macros;mac++)
if(bound_macros[mac].c==key)
return range_name(&(bound_macros[mac].r));
#ifdef TEST
error_msg("Unknown bound macro on key %d",key);
#endif
}
return cmd_funcs[main_map[key]].func_name; */
}
#endif
static void
set_usr_fmt FUN1(char *,fmtstr)
{
int u_num;
char *ptr;
static struct line usr_line;
struct line tmp_line;
char *tmp_ptr;
char *data_buf[9];
int i;
static char *names[9]= {
"Positive header",
"Negative header",
"Positive trailer",
"Negative trailer",
"Zero",
"Comma",
"Decimal point",
"Precision",
"Scale-factor"
};
tmp_line.buf=ck_malloc(10);
tmp_line.alloc=10;
tmp_ptr=tmp_line.buf;
ptr=fmtstr;
u_num=astol(&ptr);
if(u_num<1 || u_num>16 || *ptr!='\0') {
error_msg("Unknown number %s",fmtstr);
return;
}
--u_num;
get_usr_stats(u_num,data_buf);
for(i=0;i<9;i++) {
int slen;
int prevlen;
set_line(&usr_line,data_buf[i]);
if(get_inp_line(names[i],&usr_line)>1)
return;
slen=strlen(usr_line.buf);
if(tmp_line.alloc<=(tmp_ptr-tmp_line.buf)+slen) {
prevlen=tmp_ptr-tmp_line.buf;
tmp_line.alloc+=slen+1;
tmp_line.buf=ck_realloc(tmp_line.buf,tmp_line.alloc);
tmp_ptr=tmp_line.buf+prevlen;
}
strcpy(tmp_ptr,usr_line.buf);
data_buf[i]=tmp_ptr;
while(*tmp_ptr!='\0')
tmp_ptr++;
tmp_ptr++;
}
set_usr_stats(u_num, data_buf);
free(tmp_line.buf);
disp_scrn();
}
/* Modify this to write out *all* the options */
void
write_mp_options FUN1(FILE *,fp)
{
fprintf(fp,"O;%sauto;%sbackground;ticks %d\n",
auto_recalc ? "" : "no",
bkgrnd_recalc ? "" : "no",
signal_ticks/TIMER_MULT);
}
void
read_mp_options FUN1(char *,str)
{
char *np;
while(np=index(str,';')) {
*np='\0';
(void)do_set_option(str);
*np++=';';
str=np;
}
if(np=rindex(str,'\n'))
*np='\0';
(void)do_set_option(str);
}
void
set_options FUN1(char *,ptr)
{
if(do_set_option(ptr))
recenter_cur_win();
}
static void
show_options FUN0()
{
int n;
int fmts;
char *data_buf[9];
extern char *strdup();
extern void text_start EXT0();
extern void text_finish EXT0();
extern void show_window_options();
n=auto_recalc;
text_start();
text_line("auto-recalculation: %s Recalculate in background: %s",
n ? " on" : "off",bkgrnd_recalc ? "on" : "off");
text_line("make backup files: %s Copy files into backups: %s",
__make_backups ? " on" : "off",__backup_by_copying ? "on" : "off");
text_line("Asynchronous updates every %u ???",
signal_ticks/TIMER_MULT);
text_line("Print width: %5u",print_width);
text_line("");
(*show_file_opts)();
text_line("");
show_window_options();
text_line("");
fmts=usr_set_fmts();
if(fmts) {
text_line("User-defined formats:");
text_line("Fmt +Hdr -Hdr +Trlr -Trlr Zero Comma Decimal Prec Scale");
for(n=0;n<16;n++) {
if(fmts&(1<<n)) {
get_usr_stats(n,data_buf);
text_line("%3d %7s %7s %7s %7s %7s %7s %7s %5s %13s",
n+1,
data_buf[0],
data_buf[1],
data_buf[2],
data_buf[3],
data_buf[4],
data_buf[5],
data_buf[6],
data_buf[7],
data_buf[8]);
}
}
} else
text_line("No user-defined formats have been defined");
text_finish();
}
static int
do_set_option FUN1(char *,ptr)
{
int set_opt = 1;
extern int set_window_option();
while(*ptr==' ')
ptr++;
if(!strincmp("no",ptr,2)) {
ptr+=2;
set_opt=0;
while(*ptr==' ')
ptr++;
}
if(!stricmp("auto",ptr)) {
auto_recalc = set_opt;
return 0;
}
if(!stricmp("bkgrnd",ptr) || !stricmp("background",ptr)) {
bkgrnd_recalc = set_opt;
return 0;
}
if(!stricmp("backup",ptr)) {
__make_backups = set_opt;
return 0;
}
if(!stricmp("bkup_copy",ptr)) {
__backup_by_copying = set_opt;
return 0;
}
if(set_opt && !strincmp("ticks ",ptr,6)) {
extern unsigned ualarm EXT2(unsigned int, unsigned int);
ptr+=6;
signal_ticks= astol(&ptr) * TIMER_MULT;
#ifndef __TURBOC__
if(timer_active)
ualarm(signal_ticks,signal_ticks);
#endif
return 0;
}
if(set_opt && !strincmp("print ",ptr,6)) {
ptr+=6;
print_width=astol(&ptr);
return 0;
}
if(set_opt && !strincmp("file ",ptr,5)) {
#ifdef USE_DLD
char *tmpstr;
extern char *strdup();
ptr+=5;
tmpstr=ck_malloc(strlen(ptr)+20);
if(io_name) {
sprintf(tmpstr, "%s.o", ptr);
if(dld_unlink_by_file(tmpstr,0)) {
error_msg("Couldn't unlink old file format %s: %s",io_name,(dld_errno < 0 || dld_errno > dld_nerr) ? "Unknown error" : dld_errlst[dld_errno]);
goto bad_file;
}
free(io_name);
}
if(!stricmp(ptr,"panic")) {
io_name=0;
read_file = panic_read_file;
write_file = panic_write_file;
set_file_opts = panic_set_options;
show_file_opts = panic_show_options;
free(tmpstr);
return 0;
}
io_name=strdup(ptr);
sprintf(tmpstr, "%s.o", ptr);
if(dld_link(tmpstr)) {
error_msg("Couldn't link new file format %s: %s",io_name,(dld_errno < 0 || dld_errno > dld_nerr) ? "Unknown error" : dld_errlst[dld_errno]);
goto bad_file;
}
if(dld_link("libc.a"))
error_msg("Couldn't link libc.a");
if(dld_link("libm.a"))
error_msg("Couldn't link libm.a");
sprintf(tmpstr, "%s_read_file",ptr);
read_file=dld_function_executable_p(tmpstr) ? dld_get_func(tmpstr) : 0;
sprintf(tmpstr, "%s_write_file",ptr);
write_file=dld_function_executable_p(tmpstr) ? dld_get_func(tmpstr) : 0;
sprintf(tmpstr, "%s_set_options",ptr);
set_file_opts=(int(*)())(dld_function_executable_p(tmpstr) ? dld_get_func(tmpstr) : 0);
sprintf(tmpstr, "%s_show_options",ptr);
show_file_opts=dld_function_executable_p(tmpstr) ? dld_get_func(tmpstr) : 0;
if( !read_file
|| !write_file
|| !set_file_opts
|| !show_file_opts) {
char **missing;
int n;
missing=dld_list_undefined_sym();
text_start();
text_line("Undefined symbols in file format %s:",ptr);
text_line("");
for(n=0;n<dld_undefined_sym_count;n++)
text_line("%s",missing[n]);
text_line("");
text_finish();
free(missing);
error_msg("File format %s has undefined symbols: not loaded",ptr);
bad_file:
sprintf(tmpstr, "%s.o",io_name);
dld_unlink_by_file(io_name,0);
if(io_name)
free(io_name);
io_name=0;
read_file=panic_read_file;
write_file=panic_write_file;
set_file_opts=panic_set_options;
show_file_opts=panic_show_options;
}
free(tmpstr);
#else
ptr+=5;
if(!stricmp("sylk",ptr)) {
read_file = sylk_read_file;
write_file = sylk_write_file;
set_file_opts = sylk_set_options;
show_file_opts= sylk_show_options;
} else if(!stricmp("sc",ptr)) {
read_file = sc_read_file;
write_file = sc_write_file;
set_file_opts = sc_set_options;
show_file_opts= sc_show_options;
} else if(!stricmp("panic",ptr)) {
read_file = panic_read_file;
write_file = panic_write_file;
set_file_opts = panic_set_options;
show_file_opts= panic_show_options;
} else if(!stricmp("list",ptr)) {
read_file = list_read_file;
write_file = list_write_file;
set_file_opts = list_set_options;
show_file_opts= list_show_options;
/*if(ptr[4]) {
ptr+=4;
sl_sep=string_to_char(&ptr);
} */
} else
error_msg("Unknown file format %s",ptr);
#endif
return 0;
}
#ifdef USE_DLD
else if(!strincmp(ptr,"load ",5)) {
char *tmpstr;
struct function *new_funs;
struct cmd_func *new_cmds;
struct keymap **new_maps;
void (*init_cmd) EXT0();
extern unsigned long dld_get_symbol EXT1(char *);
extern void add_usr_funs EXT1(struct function *);
ptr+=5;
tmpstr=ck_malloc(strlen(ptr)+20);
sprintf(tmpstr,"%s.o",ptr);
if(dld_link(tmpstr)) {
error_msg("Couldn't link %s: %s",tmpstr,(dld_errno < 0 || dld_errno > dld_nerr) ? "Unknown error" : dld_errlst[dld_errno]);
free(tmpstr);
return 0;
}
if(dld_link("libc.a"))
error_msg("Couldn't link libc.a");
if(dld_link("libm.a"))
error_msg("Couldn't link libm.a");
if(dld_undefined_sym_count) {
char **missing;
int n;
missing=dld_list_undefined_sym();
text_start();
text_line("Undefined symbols in file format %s:",ptr);
text_line("");
for(n=0;n<dld_undefined_sym_count;n++)
text_line("%s",missing[n]);
text_line("");
text_finish();
free(missing);
error_msg("%d undefined symbols in %s",dld_undefined_sym_count,ptr);
dld_unlink_by_file(tmpstr,0);
free(tmpstr);
return 0;
}
sprintf(tmpstr,"%s_funs",ptr);
new_funs=(struct function *)dld_get_symbol(tmpstr);
if(new_funs)
add_usr_funs(new_funs);
sprintf(tmpstr,"%s_cmds", ptr);
new_cmds=(struct cmd_func *)dld_get_symbol(tmpstr);
if(new_cmds)
add_usr_cmds(new_cmds);
sprintf(tmpstr,"%s_maps", ptr);
new_maps=(struct keymap **)dld_get_symbol(tmpstr);
if(new_maps)
add_usr_maps(new_maps);
if(!new_funs && !new_cmds && !new_maps) {
error_msg("Couldn't find anything to load in %s",ptr);
sprintf(tmpstr,"%s.o",ptr);
dld_unlink_by_file(tmpstr,0);
}
sprintf(tmpstr,"%s_init",ptr);
init_cmd=dld_function_executable_p(tmpstr) ? dld_get_func(tmpstr) : 0;
if(init_cmd)
(*init_cmd)();
free(tmpstr);
return 0;
}
#endif
if(set_window_option(set_opt,ptr)==0) {
if((*set_file_opts)(set_opt,ptr))
error_msg("Unknown option '%s'",ptr);
return 0;
}
return 1;
}
void
set_line FUN2(struct line *,line, char *,string)
{
int len;
if(!string) {
if(line->alloc)
line->buf[0]='\0';
return;
}
len=strlen(string);
if(line->alloc<=len) {
if(len<LINE_MIN)
len=LINE_MIN;
else
len++;
line->alloc=len+1;
if(line->buf)
{
line->buf=ck_realloc(line->buf,line->alloc);
}
else
line->buf=ck_malloc(line->alloc);
}
strcpy(line->buf,string);
}
static void
sprint_line FUN2N(struct line *,line, char *,fmt)
{
va_list iggy;
int len;
len=strlen(fmt)+200;
if(!line->alloc) {
line->buf=ck_malloc(len);
line->alloc=len;
} else if(line->alloc<len) {
line->buf=ck_realloc(line->buf,len);
line->alloc=len;
}
var_start(iggy,fmt);
vsprintf(line->buf,fmt,iggy);
va_end(iggy);
}
static void
execute_cmd FUN1(char *,str)
{
CELL *cp;
struct macro *old;
struct rng r;
char *ptr;
for(ptr=str;*ptr && *ptr!=' ';ptr++)
;
if(*ptr)
*ptr++='\0';
else
ptr=0;
for(cur_vector=0;cur_vector<num_funcs;cur_vector++)
for(cur_cmd= &the_funcs[cur_vector][0];cur_cmd->func_name;cur_cmd++)
if(!stricmp(str,cur_cmd->func_name)) {
/* these lines stolen from map_char */
if(ptr) {
if(!cur_cmd->func_args)
error_msg("Ignoring extra operand to %s",cur_cmd->func_name);
else if(cur_cmd->func_args[0]=='n')
how_many=astol((char **)(&ptr));
else
macro_func_arg=ptr;
}
cur_chr='\0';
global_cmd(MAIN_MAP);
return;
}
if(get_abs_rng(&str,&r)) {
error_msg("Unknown command %s",str);
return;
}
if(ptr) {
error_msg("Macros can't take arguments");
return;
}
if( !(cp=find_cell(r.lr,r.lc))
|| GET_TYP(cp)!=TYP_STR
|| cp->cell_str[0]=='\0')
return;
old=rmac;
rmac=(struct macro *)obstack_alloc(¯o_stack,sizeof(struct macro));
rmac->mac_prev=old;
rmac->mac_rng= r;
rmac->mac_row=r.lr;
rmac->mac_col=r.lc;
(void)obstack_grow(¯o_stack,cp->cell_str,1+strlen(cp->cell_str));
rmac->mac_exe=(unsigned char *)obstack_finish(¯o_stack);
rmac->mac_flags=0;
}
static void
goto_region FUN1(struct rng *,r)
{
struct rng tmp;
if(mkrow!=NON_ROW) {
CELLREF cx,cy;
set_rng(&tmp,curow,cucol,mkrow,mkcol);
set_line(&in_line[12],range_name(&tmp));
cx=mkrow;
mkrow=curow;
cy=mkcol;
mkcol=cucol;
(void)move_cell_cursor(cx,cy);
} else {
set_line(&in_line[12],cell_name(curow,cucol));
(void)move_cell_cursor(r->lr,r->lc);
}
if(r->hr!=r->lr || r->hc!=r->lc) {
mkrow=r->hr;
mkcol=r->hc;
cur_status();
} else if(mkrow!=NON_ROW) {
mkrow=NON_ROW;
cur_status();
}
}
static void
set_default FUN0()
{
int fun;
char *ptr;
int num;
char buf[20];
sprintf(buf,"%d",default_width);
set_line(&wid_line,buf);
set_line(&fmt_line,fmt_to_str(default_fmt));
info_msg("Alignment %s Format %s %srotected Width %d",
jst_to_str(default_jst),
fmt_line.buf,
default_lock==LCK_LCK ? "P" : "Unp",
default_width);
fun=get_chr_prompt("[A]lignment, [F]ormat, [P]rotection, or [W]idth ");
switch(fun) {
case 'w':
case 'W':
if(get_inp_line("set-default-width",&wid_line))
break;
ptr=wid_line.buf;
num=astol(&ptr);
if(num<1)
error_msg("Can't set default width to '%s'",wid_line.buf);
else {
default_width=num;
recenter_all_win();
return;
}
break;
case 'p':
case 'P':
fun=get_chr_prompt("[P]rotected, or [U]nprotected");
if(fun=='p' || fun=='P')
default_lock= LCK_LCK;
else if(fun=='u' || fun=='U')
default_lock=LCK_UNL;
else /* if(main_map<[fun]!=BREAK_CMD) */
error_msg("Unknown char '%s'",char_to_string(fun));
break;
case 'f':
case 'F':
if(get_inp_line("set-default-format",&fmt_line))
break;
num=str_to_fmt(fmt_line.buf);
if(num==-1 || num==FMT_DEF) {
error_msg("Unknown format '%s'",fmt_line.buf);
break;
}
default_fmt=num;
disp_scrn();
return;
case 'a':
case 'A':
fun=get_chr_prompt("[L]eft, [R]ight, or [C]enter");
num=chr_to_jst(fun);
if(num!=-1 && num!=JST_DEF) {
default_jst=num;
disp_scrn();
return;
} else /* if(main_map[fun]!=BREAK_CMD) */
error_msg("Unknown Alignment '%s'",char_to_string(fun));
break;
default:
/* if(main_map[fun]!=BREAK_CMD) */
error_msg("Unknown command '%s'",char_to_string(fun));
/* else
error_msg(""); */
break;
}
cur_status();
/* topclear=2; */
}
static void
format_area FUN1(struct rng *,f)
{
int c;
int fmt,jst,wid;
CELLREF cc;
char *locked;
CELL *cp;
int fun;
char *ptr;
extern unsigned short get_nodef_width EXT1(CELLREF);
cp=find_cell(f->lr,f->lc);
if(!cp) {
fmt=FMT_DEF;
jst=JST_DEF;
} else {
fmt=GET_FMT(cp);
jst=GET_JST(cp);
}
wid=get_nodef_width(f->lc);
if(wid==0)
set_line(&wid_line,"default");
else
sprint_line(&wid_line,"%d",wid-1);
set_line(&fmt_line,fmt_to_str(fmt));
if(cp) {
if(GET_LCK(cp)==LCK_DEF)
locked = (default_lock==LCK_UNL ? "default unprotected" : "default protected");
else if(GET_LCK(cp)==LCK_UNL)
locked = "unprotected";
else if(GET_LCK(cp)==LCK_LCK)
locked = "protected";
else
locked = "Huh What?";
} else
locked = (default_lock==LCK_UNL ? "default unprotected" : "default protected");
info_msg("Alignment %s Format %s Width %s %s",
jst_to_str(jst),
fmt_line.buf,
wid_line.buf,
locked);
fun=get_chr_prompt("[A]lignment, [F]ormat, [P]rotection, or [W]idth ");
switch(fun) {
case 'f':
case 'F':
if(get_inp_line("set-format",&fmt_line))
break;
fmt=str_to_fmt(fmt_line.buf);
if(fmt!=-1)
format_region(f,fmt,-1);
else
error_msg("Unknown format '%s'",fmt_line.buf);
break;
case 'a':
case 'A':
c=get_chr_prompt("Align [L]eft, [R]ight, [C]enter, or [D]efault");
fun=chr_to_jst(c);
if(fun!=-1)
format_region(f,-1,fun);
else /* if(main_map[c]!=BREAK_CMD) */
error_msg("Unknown Justify '%s'",char_to_string(c));
break;
case 'p':
case 'P':
c=get_chr_prompt("[D]efault, [P]rotect, or [U]nprotect");
if(c=='d' || c=='D')
lock_region(f,LCK_DEF);
else if(c=='p' || c=='P')
lock_region(f,LCK_LCK);
else if(c=='u' || c=='U')
lock_region(f,LCK_UNL);
else /* if(main_map[c]!=BREAK_CMD) */
error_msg("Unknown lock %s",char_to_string(c));
break;
case 'w':
case 'W':
if(get_inp_line("set-width",&wid_line))
break;
ptr=wid_line.buf;
if(*ptr=='d' || *ptr=='D')
fun=0;
else if(isdigit(*ptr))
fun=astol(&ptr)+1;
else {
error_msg("Unknown width '%s'",wid_line.buf);
break;
}
for(cc=f->lc;;cc++) {
set_width(cc,fun);
if(cc==f->hc)
break;
}
recenter_all_win();
return;
default:
/* if(main_map[fun]!=BREAK_CMD) */
error_msg("Unknown command '%s'",char_to_string(fun));
break;
}
cur_status();
/* topclear=2; */
}
void
got_sig FUN0()
{
FILE *fp;
extern int write();
/* Using xopen_with_backup is almost certainly a bad idea, however
using open() (preferred) or fopen() causes trouble in the restore,
so we suffer. . . */
fp=xopen_with_backup("oleo.panic","w");
if(fp) {
write(1,"Performing panic save to 'oleo.panic'\r\n",39);
panic_write_file(fp,0);
xclose(fp);
} else
write(1,"Can't open 'oleo.panic'! You lose!\r\n",37);
close_display();
#ifdef FASYNC
fcntl(0,F_SETFL,term_flag);
#endif
#ifdef FIOSSAIOSTAT
if((term_flag&1)==0) {
int i=0;
ioctl(0,FIOSSAIOSTAT,&i);
}
if((term_flag&2)==0) {
int i=0;
ioctl(0,FIOSNBIO,&i);
}
#endif
exit(11);
}
static void
got_sigint FUN1(int, ign)
{
int ch;
ch=get_chr_prompt("Panic save and exit?");
if(ch=='y' || ch=='Y')
got_sig();
}
static void
start_macro FUN0()
{
if(making_macro) {
error_msg("Can't define two macros at once");
return;
}
making_macro_size=20;
making_macro=making_macro_start=ck_malloc(5+making_macro_size);
/* *making_macro++='"'; */
}
static void
end_macro FUN0()
{
union vals z;
struct rng to;
CELL *cp;
struct macro *old;
static struct line macro_line;
if(!rmac && !making_macro) {
error_msg("Not executing or defining a macro!");
return;
}
if(rmac) {
if(rmac->mac_row==rmac->mac_rng.hr && rmac->mac_col==rmac->mac_rng.hc) {
old=rmac->mac_prev;
(void)obstack_free(¯o_stack,rmac);
rmac=old;
goto deal_making;
}
if(rmac->mac_row==rmac->mac_rng.hr) {
rmac->mac_row=rmac->mac_rng.lr;
rmac->mac_col++;
} else
rmac->mac_row++;
if(!(cp=find_cell(rmac->mac_row,rmac->mac_col)) || GET_TYP(cp)!=TYP_STR || cp->cell_str[0]=='\0') {
old=rmac->mac_prev;
(void)obstack_free(¯o_stack,rmac);
rmac=old;
goto deal_making;
}
(void)obstack_grow(¯o_stack,cp->cell_str,1+strlen(cp->cell_str));
rmac->mac_exe=(unsigned char *)obstack_finish(¯o_stack);
rmac->mac_flags=0;
}
deal_making:
if(!making_macro)
return;
making_macro[0]='\0';
making_macro=0;
if(get_a_range("Put macro where",&to,¯o_line))
error_msg("Forgetting new macro");
else {
extern void set_new_value();
z.c_s=(char *)making_macro_start;
set_new_value(to.lr,to.lc,TYP_STR,&z);
}
free(making_macro_start);
}
static void
quit_cmd FUN0()
{
int c;
close_display();
#ifndef AMIGA
#ifdef FASYNC
c=fcntl(0,F_SETFL,term_flag);
#endif
#ifdef FIOSSAIOSTAT
if((term_flag&1)==0) {
int i=0;
ioctl(0,FIOSSAIOSTAT,&i);
}
if((term_flag&2)==0) {
int i=0;
ioctl(0,FIOSNBIO,&i);
}
#endif
#endif
exit(0);
}
static void
bound_macro FUN1(int, num)
{
struct macro *old;
CELL *cp;
/* CELLREF rr,cc; */
cp=find_cell(bound_macros[num].lr,bound_macros[num].lc);
if(!cp || GET_TYP(cp)!=TYP_STR || cp->cell_str[0]=='\0')
return;
old=rmac;
rmac=(struct macro *)obstack_alloc(¯o_stack,sizeof(struct macro));
rmac->mac_prev=old;
rmac->mac_rng=bound_macros[num];
rmac->mac_row=bound_macros[num].lr;
rmac->mac_col=bound_macros[num].lc;
(void)obstack_grow(¯o_stack,cp->cell_str,1+strlen(cp->cell_str));
rmac->mac_exe=(unsigned char *)obstack_finish(¯o_stack);
rmac->mac_flags=0;
}
static void
mark_cell_cmd FUN0()
{
mkrow=curow;
mkcol=cucol;
cur_status();
}
static void
recalc_cmd FUN0()
{
current_cycle++;
while(eval_next_cell())
;
}
static void
desc_key_cmd FUN0()
{
error_msg("Key: ");
map_chr(MAIN_MAP);
if(!cur_cmd)
info_msg("%s is unbound", char_to_string(cur_chr));
else
info_msg("%s --> %s",char_to_string(cur_chr), cur_cmd->func_name);
}
static void
bind_key_cmd FUN1(char *,text)
{
int map;
int c;
/* int n; */
int vec;
int code;
char *ptr;
char *cmdstr;
struct rng rng;
struct cmd_func *tmpfunc;
static struct line tmpline;
for(ptr=text;*ptr && *ptr!=' ';ptr++)
;
if(!*ptr) {
if(get_inp_line("Command",&tmpline))
return;
ptr=tmpline.buf;
} else
*ptr++='\0';
while(*ptr==' ')
ptr++;
cmdstr=ptr;
while(*ptr && *ptr!=' ')
ptr++;
if(!*ptr)
c=get_chr_prompt("Key: ");
else {
*ptr++='\0';
c=string_to_char(&ptr);
}
for(map=0;map<num_maps;map++)
if(!strcmp(text,map_names[map]))
break;
if(map==num_maps) {
error_msg("Can't find keymap '%s'",text);
goto fail;
}
for(vec=0;vec<num_funcs;vec++) {
for(code=0;the_funcs[vec][code].func_name;code++)
if(!stricmp(cmdstr,the_funcs[vec][code].func_name))
goto fini;
}
for(code=0;code<num_maps;code++) {
if(!strcmp(cmdstr,map_names[code])) {
vec=255;
goto fini;
}
}
if(get_abs_rng(&cmdstr,&rng)) {
error_msg("Unknown command '%s'",cmdstr);
goto fail;
}
vec=bound_macro_vec;
for(code=0;code<n_bound_macros;code++) {
if(!bcmp(&bound_macros[code],&rng,sizeof(struct rng)))
goto fini;
}
ptr=range_name(&rng);
if(!bound_macro_vec) {
bound_macros=ck_malloc(sizeof(struct rng));
n_bound_macros=1;
tmpfunc=ck_malloc(sizeof(struct cmd_func));
bound_macro_vec=add_usr_cmds(tmpfunc);
} else {
n_bound_macros++;
bound_macros=ck_realloc(bound_macros,n_bound_macros*sizeof(struct rng));
the_funcs[bound_macro_vec]=ck_realloc(the_funcs[bound_macro_vec],n_bound_macros*sizeof(struct cmd_func));
tmpfunc= &the_funcs[bound_macro_vec][n_bound_macros-1];
}
bound_macros[n_bound_macros-1]=rng;
tmpfunc->func_args=ck_malloc(strlen(ptr)+5);
tmpfunc->func_args[0]='n';
tmpfunc->func_args[1]='a'+(n_bound_macros-1)/26;
tmpfunc->func_args[2]='a'+(n_bound_macros-1)%26;
tmpfunc->func_args[3]='\0';
tmpfunc->func_name=tmpfunc->func_args+4;
strcpy(tmpfunc->func_name,ptr);
tmpfunc->func_flags=ALL;
tmpfunc->func_func=bound_macro;
fini:
do_bind_key(the_maps[map],c,vec,code);
fail:
sprint_line(&in_line[16],"%s %s %s",text,cmdstr,char_to_string(c));
}
static void
do_bind_key FUN4(struct keymap *,map, int,key, unsigned char,vector, unsigned char,code)
{
struct keymap *m;
struct key *k;
int n;
for(m=map;m;m=m->map_next) {
if(key+1>=m->lochr && key-1<=m->hichr)
break;
if(m->map_end)
m=0;
}
if(m->map_dense) {
if(vector==m->keys[0].vector && code==m->keys[0].code) {
if(key<m->lochr)
m->lochr=key;
if(key>m->hichr)
m->hichr=key;
return;
} else if(m->lochr!=m->hichr)
m=0;
else
m->map_dense=0;
}
if(m==0) {
m=ck_malloc(sizeof(struct keymap));
*m= *map;
map->map_next=m;
m=map;
m->map_end=0;
m->map_dense=1;
m->map_malloc=2;
m->lochr=key;
m->hichr=key;
m->keys=ck_malloc(sizeof(struct key));
}
if(key<m->lochr) {
n=sizeof(struct key)*(1+m->hichr-m->lochr);
k=ck_malloc(n+sizeof(struct key));
bcopy(&m->keys[0],&k[1],n);
if(m->map_malloc==2)
free(m->keys);
m->keys=k;
m->lochr=key;
m->map_malloc=2;
}
if(key>m->hichr) {
if(m->map_malloc==2)
{
m->keys=ck_realloc(m->keys,sizeof(struct key)*(1+m->hichr-m->lochr));
}
else {
n=sizeof(struct key)*(1+m->hichr-m->lochr);
k=ck_malloc(n+sizeof(struct key));
bcopy(&m->keys[0],k,n);
m->keys=k;
m->map_malloc=2;
}
m->hichr=key;
}
if(!m->map_malloc) {
n=sizeof(struct key)*(1+m->hichr-m->lochr);
k=ck_malloc(n);
bcopy(&m->keys[0],k,n);
m->keys=k;
m->map_malloc=2;
}
m->keys[key-m->lochr].vector=vector;
m->keys[key-m->lochr].code=code;
}
static void
interact_macro_cmd FUN0()
{
error_msg("Command not implemented");
return;
}
static void
kill_cell_cmd FUN0()
{
CELL *cp;
cp=find_cell(curow,cucol);
if(!cp)
return;
if((GET_LCK(cp)==LCK_DEF && default_lock==LCK_LCK) || GET_LCK(cp)==LCK_LCK) {
error_msg("Cell %s is locked",cell_name(curow,cucol));
return;
}
new_value(curow,cucol,"");
cp->cell_flags=0;
modified=1;
}
static void
format_cell_cmd FUN0()
{
struct rng to;
to.lr=to.hr=curow;
to.lc=to.hc=cucol;
format_area(&to);
}
static void
kill_all_cmd FUN0()
{
clear_spreadsheet();
disp_scrn();
}
#if 0
static void
do_ansi_cmd FUN0()
{
int c;
c=get_chr();
if(c>='A' && c<='D')
shift_cell_cursor(c-'A');
else
/* ? ? ? */;
}
#endif
static void
do_input_cmd FUN2(int, n, int,c)
{
CELL *cp;
char *fail;
extern char *cell_value_string EXT2(CELLREF, CELLREF);
switch(n) {
/* Edit cell */
case 0:
if(cp=find_cell(curow,cucol)) {
set_line(&val_line,decomp(curow,cucol,cp));
decomp_free();
} else
set_line(&val_line,0);
break;
/* Edit Cell Value */
case 1:
set_line(&val_line,cell_value_string(curow,cucol));
break;
case 2: /* Set-cell */
set_line(&val_line,"x");
val_line.buf[0]=c;
break;
/* New Def Cell */
case 3:
break;
#ifdef TEST
default:
panic("Unknown value in do_input_cell (%d)",n);
#endif
}
cp=find_cell(curow,cucol);
if(((!cp || GET_LCK(cp)==LCK_DEF) && default_lock==LCK_LCK) || (cp && GET_LCK(cp)==LCK_LCK)) {
error_msg("Cell %s is locked",cell_name(curow,cucol));
return;
}
setrow=curow;
setcol=cucol;
if(get_inp_line("set-cell",&val_line)>1)
return;
fail=new_value(setrow,setcol,val_line.buf);
if(fail)
error_msg(fail);
else
modified=1;
}
static void
do_break_cmd FUN0()
{
if(mkrow!=NON_ROW) {
mkrow=NON_ROW;
how_many=1;
cur_status();
}
}
static void
digit_cmd FUN1(int, magic)
{
struct keymap *map;
for(map=the_maps[DIGIT_MAP];map->map_end==0;map=map->map_next)
;
map->map_next= the_maps[magic];
how_many=0;
do {
how_many=how_many * 10 + cur_cmd - &cmd_funcs[DIGIT_0];
cur_status();
map_chr(DIGIT_MAP);
} while(cur_cmd>= &cmd_funcs[DIGIT_0] && cur_cmd<= &cmd_funcs[DIGIT_9]);
}